﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
namespace Host
{
    public class ComponentsFactory
    {
        private Dictionary<string, Func<IComponents>> providers = new Dictionary<string, Func<IComponents>>();
        private static ComponentsFactory components_factory = new ComponentsFactory();

        private ComponentsFactory()
        {
            //自动注册所有的组建

        }

        /// <summary>
        /// 获取工厂单例
        /// </summary>
        /// <returns>The instance.</returns>
        public static ComponentsFactory GetInstance()
        {
            return components_factory;
        }

        /// <summary>
        /// 注册供应商
        /// </summary>
        /// <param name="name">Name.</param>
        /// <param name="func">Func.</param>
        public void RegisterProvider(string name, Func<IComponents> func)
        {
            if (!providers.ContainsKey(name))
            {
                providers.Add(name, func);
            }
        }

        /// <summary>
        /// 清理供应商
        /// </summary>
        public void ClearProvider()
        {
            providers.Clear();
        }

        /// <summary>
        /// 移除供应商
        /// </summary>
        /// <param name="name">Name.</param>
        public void RemoveProvider(string name)
        {
            providers.Remove(name);
        }

        /// <summary>
        /// 创建组件
        /// </summary>
        /// <returns>The components.</returns>
        /// <param name="name">Name.</param>
        public IComponents CreateComponents(string name)
        {
            IComponents data = null;
            if (providers.ContainsKey(name))
            {
                data = providers[name]();
            }
            return data;
        }

        /// <summary>
        /// 获取程序集中所有组件的对象实例
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static IEnumerable<IComponents> GetAllComponentsFromAssembly(string name)
        {
            List<IComponents> components = new List<IComponents>();

            Assembly item_calss = null;

            try
            {
                item_calss = AssemblyEx.SearchAssembly(name);

                if (item_calss == null)
                    item_calss = Assembly.Load(name);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            if (item_calss == null)
                return null;

            //加载项目中的所有合适的类
            foreach (var item in item_calss.GetTypes())
            {
                if (item.IsSubclassOf(typeof(IComponents)))
                {
                    ComponentsFactory.GetInstance().RegisterProvider(item.Name, () => { return (IComponents)item_calss.CreateInstance(item.FullName); });

                    try
                    {
                        components.Add((IComponents)item_calss.CreateInstance(item.FullName));
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
            }

            return components;
        }

        /// <summary>
        /// 填充Host
        /// </summary>
        /// <param name="host">Host.</param>
        /// <param name="data">Data.</param>
        public void FillHostByComponentsData(Host host, Dictionary<string, List<KeyValuePair<string, object>>> data)
        {
            if (host == null)
                return;

            if (data == null)
                return;

            foreach (var item in data)
            {
                IComponents components = CreateComponents(item.Key);
                if (components == null)
                    continue;

                foreach (var kv in item.Value ?? new List<KeyValuePair<string, object>>())
                {
                    var field_info = components.GetType().GetField(kv.Key);
                    if (field_info == null)
                        continue;

                    field_info.SetValue(components, kv.Value);
                }

                host.AddComponents(components);
            }
        }
    }
}
